<template>
  <div class="koi-flex">
    <KoiSearch :isFold="false" :showSearch="showSearch">
      <!-- 搜索条件 -->
      <el-form :inline="true">
        <el-form-item :label="$t('menu.system.user.search.label.loginName')" prop="loginName">
          <el-input
            :placeholder="$t('menu.system.user.search.placeholder.loginName')"
            v-model="searchParams.loginName"
            clearable
            style="width: 220px"
            @keyup.enter.native="handleListPage"
          ></el-input>
        </el-form-item>
        <el-form-item :label="$t('menu.system.user.search.label.userName')" prop="userName">
          <el-input
            :placeholder="$t('menu.system.user.search.placeholder.userName')"
            v-model="searchParams.userName"
            clearable
            style="width: 220px"
            @keyup.enter.native="handleListPage"
          ></el-input>
        </el-form-item>
        <el-form-item :label="$t('menu.system.user.search.label.phone')" prop="phone">
          <el-input
            :placeholder="$t('menu.system.user.search.placeholder.phone')"
            v-model="searchParams.phone"
            clearable
            style="width: 220px"
            @keyup.enter.native="handleListPage"
          ></el-input>
        </el-form-item>
        <!-- 部门级联选择框 -->
        <el-form-item :label="$t('menu.system.user.search.label.deptId')" prop="deptId">
          <el-cascader
            :placeholder="$t('menu.system.user.search.placeholder.deptId')"
            v-model="searchParams.deptId"
            :options="cascaderOptions"
            :props="{ expandTrigger: 'hover', emitPath: false, checkStrictly: true }"
            filterable
            clearable
            style="width: 260px"
          >
            <template #default="{ node, data }">
              <span>{{ data.label }}</span>
              <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
            </template>
          </el-cascader>
        </el-form-item>
        <el-form-item :label="$t('menu.system.user.search.label.loginTime')" prop="loginTime">
          <el-date-picker
            v-model="dateRange"
            type="datetimerange"
            value-format="YYYY-MM-DD HH:mm:ss"
            :start-placeholder="$t('msg.beginTime')"
            :range-separator="$t('msg.to')"
            :end-placeholder="$t('msg.endTime')"
            :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="search" plain @click="handleSearch()" v-auth="['system:user:search']">{{
            $t("button.search")
          }}</el-button>
          <el-button type="danger" icon="refresh" plain @click="resetSearch()">{{ $t("button.reset") }}</el-button>
        </el-form-item>
      </el-form>
    </KoiSearch>
    <KoiCard>
      <!-- 表格头部按钮 -->
      <el-row :gutter="10">
        <el-col :span="1.5" v-auth="['system:user:add']">
          <el-button type="primary" icon="plus" plain @click="handleAdd()">{{ $t("button.add") }}</el-button>
        </el-col>
        <el-col :span="1.5" v-auth="['system:user:update']">
          <el-button type="success" icon="edit" plain @click="handleUpdate()" :disabled="single">{{
            $t("button.update")
          }}</el-button>
        </el-col>
        <el-col :span="1.5" v-auth="['system:user:delete']">
          <el-button type="danger" icon="delete" plain @click="handleBatchDelete()" :disabled="multiple">{{
            $t("button.delete")
          }}</el-button>
        </el-col>
        <el-col :span="1.5" v-auth="['*']">
          <el-button type="primary" icon="edit" plain @click="handleAssignRoles()" :disabled="checked">{{
            $t("button.role")
          }}</el-button>
        </el-col>
        <el-col :span="1.5" v-auth="['*']">
          <el-button type="success" icon="edit" plain @click="handleAssignPosts()" :disabled="checked">{{
            $t("button.post")
          }}</el-button>
        </el-col>
        <el-col :span="1.5" v-auth="['system:user:export']">
          <el-button type="warning" icon="download" plain @click="handleExportExcel(searchParams)" :loading:="excelLoading">{{
            $t("button.export")
          }}</el-button>
        </el-col>
        <el-col :span="1.5" v-auth="['system:user:import']">
          <el-button type="info" icon="upload" plain @click="handleImportExcel()">{{ $t("button.import") }}</el-button>
        </el-col>
        <KoiToolbar v-model:showSearch="showSearch" @refreshTable="handleListPage"></KoiToolbar>
      </el-row>

      <div class="h-20px"></div>
      <!-- 数据表格 :data="tableList" -->
      <!-- 静态数据表格分页 :data="tableList.slice((searchParams.pageNo - 1) * searchParams.pageSize, searchParams.pageNo * searchParams.pageSize)" -->
      <el-table
        v-loading="loading"
        border
        :data="tableList"
        :empty-text="$t('msg.null')"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column :label="$t('table.number')" prop="userId" width="80px" align="center" type="index"></el-table-column>
        <el-table-column
          :label="$t('menu.system.user.table.loginName')"
          prop="loginName"
          width="150px"
          align="center"
          :show-overflow-tooltip="true"
        ></el-table-column>
        <el-table-column
          :label="$t('menu.system.user.table.deptName')"
          prop="deptName"
          width="180px"
          align="center"
          :show-overflow-tooltip="true"
        ></el-table-column>
        <el-table-column :label="$t('menu.system.user.table.avatar')" prop="avatar" width="80px" align="center">
          <template #default="scope">
            <div class="flex flex-justify-center">
              <el-image
                class="rounded-full w-36px h-36px"
                :preview-teleported="true"
                :preview-src-list="[scope.row.avatar]"
                :src="
                  scope.row.avatar != null && scope.row.avatar != ''
                    ? scope.row.avatar
                    : 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
                "
              >
                <template #error>
                  <el-icon class="text-[--el-color-primary]" :size="36">
                    <CircleCloseFilled />
                  </el-icon>
                </template>
              </el-image>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          :label="$t('menu.system.user.table.userName')"
          prop="userName"
          width="120px"
          align="center"
          :show-overflow-tooltip="true"
        ></el-table-column>
        <el-table-column
          :label="$t('menu.system.user.table.email')"
          prop="email"
          width="220px"
          align="center"
          :show-overflow-tooltip="true"
        ></el-table-column>
        <el-table-column
          :label="$t('menu.system.user.table.phone')"
          prop="phone"
          width="130px"
          align="center"
          :show-overflow-tooltip="true"
        ></el-table-column>
        <el-table-column :label="$t('menu.system.user.table.userType')" prop="userType" width="100px" align="center">
          <template #default="scope">
            <KoiTag :tagOptions="koiDicts.sys_user_type" :value="scope.row.userType"></KoiTag>
          </template>
        </el-table-column>
        <el-table-column :label="$t('menu.system.user.table.sex')" prop="sex" width="90px" align="center">
          <template #default="scope">
            <KoiTag :tagOptions="koiDicts.sys_user_sex" :value="scope.row.sex"></KoiTag>
          </template>
        </el-table-column>
        <!-- 注意：如果后端数据返回的是字符串"0" OR "1"，这里的active-value AND inactive-value不需要加冒号，会认为是字符串，否则：后端返回是0 AND 1数字，则需要添加冒号 -->
        <el-table-column :label="$t('menu.system.user.table.userStatus')" prop="userStatus" width="100px" align="center">
          <template #default="scope">
            <el-switch
              v-model="scope.row.userStatus"
              :active-text="$t('dict.sys_switch_status.open')"
              :inactive-text="$t('dict.sys_switch_status.stop')"
              active-value="0"
              inactive-value="1"
              :inline-prompt="true"
              @change="handleSwitch(scope.row)"
            >
            </el-switch>
          </template>
        </el-table-column>
        <el-table-column
          :label="$t('menu.system.user.table.loginTime')"
          prop="loginTime"
          width="180px"
          align="center"
        ></el-table-column>
        <el-table-column
          :label="$t('table.operate')"
          align="center"
          width="150"
          fixed="right"
          v-auth="['system:user:update', 'system:user:delete', 'system:user:resetPwd']"
        >
          <template #default="{ row }">
            <el-tooltip :content="$t('button.update')" placement="top">
              <el-button
                type="primary"
                icon="Edit"
                circle
                plain
                @click="handleUpdate(row)"
                v-auth="['system:user:update']"
              ></el-button>
            </el-tooltip>
            <el-tooltip :content="$t('button.delete')" placement="top">
              <el-button
                type="danger"
                icon="Delete"
                circle
                plain
                @click="handleDelete(row)"
                v-auth="['system:user:delete']"
              ></el-button>
            </el-tooltip>
            <el-tooltip :content="$t('button.password')" placement="top">
              <el-button
                type="warning"
                icon="Key"
                circle
                plain
                @click="handleResetPwd(row)"
                v-auth="['system:user:resetPwd']"
              ></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>

      <div class="h-20px"></div>
      <!-- 分页 -->
      <el-pagination
        background
        v-model:current-page="searchParams.pageNo"
        v-model:page-size="searchParams.pageSize"
        v-show="total > 0"
        :page-sizes="[10, 20, 50, 100, 200]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="handleListPage"
        @current-change="handleListPage"
      />

      <!-- 添加 OR 修改 -->
      <KoiDrawer
        ref="koiDrawerRef"
        :title="title"
        @koiConfirm="handleConfirm"
        @koiCancel="handleCancel"
        :loading="confirmLoading"
      >
        <template #content>
          <el-form ref="formRef" :rules="rules" :model="form" label-width="auto" status-icon>
            <el-row>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.loginName')" prop="loginName">
                  <el-input
                    v-model="form.loginName"
                    :placeholder="$t('menu.system.user.form.placeholder.loginName')"
                    maxlength="16"
                    show-word-limit
                    clearable
                  />
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }" v-if="showPwd">
                <el-form-item :label="$t('menu.system.user.form.label.password')" prop="password">
                  <el-input
                    type="password"
                    v-model="form.password"
                    show-password
                    :placeholder="$t('menu.system.user.form.placeholder.password')"
                    clearable
                  />
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.userName')" prop="userName">
                  <el-input
                    v-model="form.userName"
                    :placeholder="$t('menu.system.user.form.placeholder.userName')"
                    maxlength="16"
                    show-word-limit
                    clearable
                  />
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <!-- 部门级联选择框 -->
                <el-form-item :label="$t('menu.system.user.form.label.deptId')" prop="deptId">
                  <el-cascader
                    class="flex-1"
                    :placeholder="$t('menu.system.user.form.placeholder.deptId')"
                    v-model="form.deptId"
                    :options="cascaderOptions"
                    :props="{ expandTrigger: 'hover', emitPath: false, checkStrictly: true }"
                    filterable
                    clearable
                  >
                    <template #default="{ node, data }">
                      <span>{{ data.label }}</span>
                      <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
                    </template>
                  </el-cascader>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }" v-auth="['system:user:post']">
                <el-form-item :label="$t('menu.system.user.form.label.postIds')" prop="postIds">
                  <el-select v-model="form.postIds" multiple :placeholder="$t('menu.system.user.form.placeholder.postIds')">
                    <el-option v-for="item in postOptions" :key="item.value" :label="item.label" :value="item.value" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }" v-auth="['system:user:role']">
                <el-form-item :label="$t('menu.system.user.form.label.roleIds')" prop="roleIds">
                  <el-select v-model="form.roleIds" multiple :placeholder="$t('menu.system.user.form.placeholder.roleIds')">
                    <el-option v-for="item in roleOptions" :key="item.value" :label="item.label" :value="item.value" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.userType')" prop="userType">
                  <el-select v-model="form.userType" :placeholder="$t('menu.system.user.form.placeholder.userType')" clearable>
                    <el-option
                      v-for="item in koiDicts.sys_user_type"
                      :key="item.dictValue"
                      :label="item.dictLabel"
                      :value="item.dictValue"
                    />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.userStatus')" prop="userStatus">
                  <el-select
                    v-model="form.userStatus"
                    :placeholder="$t('menu.system.user.form.placeholder.userStatus')"
                    clearable
                  >
                    <el-option :label="$t('dict.sys_switch_status.open')" value="0" />
                    <el-option :label="$t('dict.sys_switch_status.stop')" value="1" />
                  </el-select>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.sex')" prop="sex">
                  <el-radio-group v-model="form.sex" :placeholder="$t('menu.system.user.form.placeholder.sex')">
                    <el-radio value="1" border>{{ $t("dict.sys_user_sex.man") }}</el-radio>
                    <el-radio value="2" border>{{ $t("dict.sys_user_sex.woman") }}</el-radio>
                    <el-radio value="0" border>{{ $t("dict.sys_user_sex.unknown") }}</el-radio>
                  </el-radio-group>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.avatar')" prop="avatar">
                  <KoiUploadImage v-model:imageUrl="form.avatar">
                    <template #content>
                      <el-icon>
                        <Avatar />
                      </el-icon>
                      <span>{{ $t("menu.system.user.form.placeholder.avatar.description") }}</span>
                    </template>
                    <template #tip>{{ $t("menu.system.user.form.placeholder.avatar.tip") }}</template>
                  </KoiUploadImage>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.phone')" prop="phone">
                  <el-input
                    v-model="form.phone"
                    :placeholder="$t('menu.system.user.form.placeholder.phone')"
                    maxlength="16"
                    show-word-limit
                    clearable
                  ></el-input>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.email')" prop="email">
                  <el-input
                    v-model="form.email"
                    :placeholder="$t('menu.system.user.form.placeholder.email')"
                    maxlength="32"
                    show-word-limit
                    clearable
                  ></el-input>
                </el-form-item>
              </el-col>
              <el-col :sm="{ span: 24 }" :xs="{ span: 24 }">
                <el-form-item :label="$t('menu.system.user.form.label.remark')" prop="remark">
                  <el-input
                    v-model="form.remark"
                    :rows="5"
                    type="textarea"
                    :placeholder="$t('menu.system.user.form.placeholder.remark')"
                    maxlength="64"
                    show-word-limit
                    clearable
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </el-form>
        </template>
      </KoiDrawer>

      <KoiDialog ref="koiRoleDialogRef" :title="$t('button.role')" :height="450" :footerHidden="true">
        <template #content>
          <div class="flex flex-justify-center">
            <el-transfer
              :props="{
                key: 'value',
                label: 'label'
              }"
              :titles="[$t('menu.system.user.transfer.role'), $t('button.role')]"
              target-order="original"
              filterable
              :filter-placeholder="$t('msg.keyword')"
              :format="{
                noChecked: '${total}',
                hasChecked: '${checked}/${total}'
              }"
              v-model="transferRightRoleList"
              :data="transferLeftRoleList"
              @change="handleRoleTransferChange"
            />
          </div>
        </template>
      </KoiDialog>

      <KoiDialog ref="koiPostDialogRef" :title="$t('button.post')" :height="450" :footerHidden="true">
        <template #content>
          <div class="flex flex-justify-center">
            <el-transfer
              :props="{
                key: 'value',
                label: 'label'
              }"
              :titles="[$t('menu.system.user.transfer.post'), $t('button.post')]"
              target-order="original"
              filterable
              :filter-placeholder="$t('msg.keyword')"
              :format="{
                noChecked: '${total}',
                hasChecked: '${checked}/${total}'
              }"
              v-model="transferRightPostList"
              :data="transferLeftPostList"
              @change="handlePostTransferChange"
            />
          </div>
        </template>
      </KoiDialog>

      <KoiExcel ref="koiExcelRef" @handleTemplateExcel="handleTemplateExcel"></KoiExcel>
    </KoiCard>
  </div>
</template>

<script setup name="userPage" lang="ts">
import { nextTick, ref, reactive, onMounted } from "vue";
import { koiMsgSuccess, koiMsgWarning, koiMsgError } from "@/utils/koi.ts";
import { ElMessageBox, ElLoading } from "element-plus";
import {
  listPage,
  getById,
  add,
  update,
  deleteById,
  batchDelete,
  updateStatus,
  resetPwd,
  exportData,
  downloadTemplate
} from "@/api/system/user/index.ts";
import { listNormalTransferRole, listRoleElSelect, assignRolesToUsers } from "@/api/system/role/index.ts";
import { listNormalTransferPost, listPostElSelect, assignPostsToUsers } from "@/api/system/post/index.ts";
import { handleTree } from "@/utils/index.ts";
import { cascaderList } from "@/api/system/dept/index.ts";
import { koiDatePicker } from "@/utils/index.ts";
import { useI18n } from "vue-i18n";
import { useKoiDict } from "@/hooks/dicts/index.ts";

const { koiDicts } = useKoiDict(["sys_user_type", "sys_user_sex"]);
const { t } = useI18n();
// 表格加载动画Loading
const loading = ref(false);
// 是否显示搜索表单[默认显示]
const showSearch = ref<boolean>(true);
// 表格数据
const tableList = ref<any>([]);
// 时间
const dateRange = ref();

// 查询参数
const searchParams = ref({
  pageNo: 1, // 第几页
  pageSize: 10, // 每页显示多少条
  loginName: undefined,
  userName: undefined,
  phone: undefined,
  deptId: undefined
});

const total = ref<number>(0);

/** 重置搜索参数 */
const resetSearchParams = () => {
  searchParams.value = {
    pageNo: 1,
    pageSize: 10,
    loginName: undefined,
    userName: undefined,
    phone: undefined,
    deptId: undefined
  };
  dateRange.value = [];
};

// 级联下拉框
const cascaderOptions = ref<any>([]);

/** 部门级联数据 */
const handleCascader = async () => {
  try {
    cascaderOptions.value = [];
    const res: any = await cascaderList();
    cascaderOptions.value = handleTree(res.data, "value");
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

/** 搜索 */
const handleSearch = () => {
  searchParams.value.pageNo = 1;
  handleListPage();
};

/** 重置 */
const resetSearch = () => {
  resetSearchParams();
  handleListPage();
};

/** @current-change：点击分页组件页码发生变化：例如：切换第2、3页 OR 上一页 AND 下一页 OR 跳转某一页 */
/** @size-change：点击分页组件下拉选择条数发生变化：例如：选择10条/页、20条/页等 */
// 分页查询，@current-change AND @size-change都会触发分页，调用后端分页接口
/** 数据表格 */
const handleListPage = async () => {
  try {
    loading.value = true;
    tableList.value = []; // 重置表格数据
    const res: any = await listPage(koiDatePicker(searchParams.value, dateRange.value));
    tableList.value = res.data.records;
    total.value = res.data.total;
    loading.value = false;
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

/** 数据表格[删除、批量删除等刷新使用] */
const handleTableData = async () => {
  try {
    const res: any = await listPage(koiDatePicker(searchParams.value, dateRange.value));
    tableList.value = res.data.records;
    total.value = res.data.total;
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

onMounted(() => {
  // 获取表格数据
  handleListPage();
  handleCascader();
});

const ids = ref([]); // 选择数组
const single = ref<boolean>(true); // 非单个禁用
const multiple = ref<boolean>(true); // 非多个禁用
const checked = ref<boolean>(true); // 是否选中

/** 是否多选 */
const handleSelectionChange = (selection: any) => {
  ids.value = selection.map((item: any) => item.userId);
  single.value = selection.length != 1; // 单选
  multiple.value = !selection.length; // 多选
  checked.value = !(selection.length > 0); // 是否选中
};

// 岗位下拉框
const postOptions = ref<any>([]);
// 角色下拉框
const roleOptions = ref<any>([]);
// 添加显示密码框，修改隐藏密码框
const showPwd = ref(true);

// 岗位下拉框
const listPostOptions = async () => {
  try {
    const res: any = await listPostElSelect();
    postOptions.value = res.data;
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

// 角色下拉框
const listRoleOptions = async () => {
  try {
    const res: any = await listRoleElSelect();
    roleOptions.value = res.data;
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

/** 添加 */
const handleAdd = () => {
  // 打开抽屉
  koiDrawerRef.value.koiOpen();
  // 重置表单
  resetForm();
  // 显示密码框
  showPwd.value = true;
  // 岗位下拉框
  listPostOptions();
  // 角色下拉框
  listRoleOptions();
  // 标题
  title.value = t("button.add");
  form.value.userStatus = "0";
};

/** 回显数据 */
const handleEcho = async (id: any) => {
  if (id == null || id == "") {
    koiMsgWarning(t("msg.selectData"));
    return;
  }
  try {
    const res: any = await getById(id);
    form.value = res.data;
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

/** 修改 */
const handleUpdate = async (row?: any) => {
  // 打开抽屉
  koiDrawerRef.value.koiOpen();
  // 重置表单
  resetForm();
  // 隐藏密码框
  showPwd.value = false;
  // 标题
  title.value = t("button.update");
  const userId = row ? row.userId : ids.value[0];
  // 回显数据
  handleEcho(userId);
  // 岗位下拉框
  listPostOptions();
  // 角色下拉框
  listRoleOptions();
};

// 添加 OR 修改抽屉Ref
const koiDrawerRef = ref();
// 标题
const title = ref();
// form表单Ref
const formRef = ref<any>();
// form表单
let form = ref<any>({
  loginName: undefined,
  password: "yu123456",
  userName: undefined,
  deptId: undefined,
  postIds: [],
  roleIds: [],
  userType: "1",
  userStatus: "0",
  sex: "0",
  avatar: undefined,
  phone: undefined,
  remark: undefined
});

/** 清空表单数据 */
const resetForm = () => {
  // 等待 DOM 更新完成
  nextTick(() => {
    if (formRef.value) {
      // 重置该表单项，将其值重置为初始值，并移除校验结果
      formRef.value.resetFields();
    }
  });
  form.value = {
    loginName: undefined,
    password: "yu123456",
    userName: undefined,
    userType: "1",
    userStatus: "0",
    sex: "0",
    avatar: undefined,
    phone: undefined,
    email: undefined,
    remark: undefined
  };
  postOptions.value = [];
  roleOptions.value = [];
};

/** 表单规则 */
const rules = reactive({
  loginName: [{ required: true, message: t("menu.system.user.rules.loginName.required"), trigger: "blur" }],
  password: [
    {
      required: true,
      message: t("menu.system.user.rules.password.required"),
      trigger: "blur"
    },
    {
      validator: (_rule: any, value: any, callback: any) => {
        if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9]{6,20}$/.test(value)) {
          callback(new Error(t("menu.system.user.rules.password.validator")));
        } else {
          callback();
        }
      },
      trigger: "blur"
    }
  ],
  userName: [{ required: true, message: t("menu.system.user.rules.userName.required"), trigger: "blur" }],
  deptId: [{ required: true, message: t("menu.system.user.rules.deptId.required"), trigger: "blur" }],
  postIds: [{ required: true, message: t("menu.system.user.rules.postIds.required"), trigger: "blur" }],
  roleIds: [{ required: true, message: t("menu.system.user.rules.roleIds.required"), trigger: "blur" }],
  userType: [{ required: true, message: t("menu.system.user.rules.userType.required"), trigger: "blur" }],
  sex: [{ required: true, message: t("menu.system.user.rules.sex.required"), trigger: "blur" }],
  userStatus: [{ required: true, message: t("menu.system.user.rules.userStatus.required"), trigger: "blur" }],
  phone: [{ required: true, message: t("menu.system.user.rules.phone.required"), trigger: "blur" }]
});

// 确定按钮是否显示Loading
const confirmLoading = ref(false);

/** 确定  */
const handleConfirm = () => {
  if (!formRef.value) return;
  confirmLoading.value = true;
  (formRef.value as any).validate(async (valid: any) => {
    if (valid) {
      if (form.value.userId != null && form.value.userId != "") {
        try {
          await update(form.value);
          koiMsgSuccess(t("msg.success"));
          confirmLoading.value = false;
          koiDrawerRef.value.koiQuickClose();
          resetForm();
          handleListPage();
        } catch (error) {
          console.log(error);
          confirmLoading.value = false;
          koiMsgError(t("msg.fail"));
        }
      } else {
        try {
          await add(form.value);
          koiMsgSuccess(t("msg.success"));
          confirmLoading.value = false;
          koiDrawerRef.value.koiQuickClose();
          resetForm();
          handleListPage();
        } catch (error) {
          console.log(error);
          confirmLoading.value = false;
          koiMsgError(t("msg.fail"));
        }
      }
    } else {
      koiMsgError(t("msg.validFail"));
      confirmLoading.value = false;
    }
  });
};

/** 取消 */
const handleCancel = () => {
  koiDrawerRef.value.koiClose();
};

/** 状态开关 */
const handleSwitch = (row: any) => {
  let text = row.userStatus === "0" ? t("dict.sys_switch_status.open") : t("dict.sys_switch_status.stop");
  if (!row.userId || !row.userStatus) {
    row.userStatus = row.userStatus == "0" ? "1" : "0";
    koiMsgWarning(t("msg.selectData"));
    return;
  }
  ElMessageBox.confirm(t("msg.confirmWant") + "[" + text + "]-[" + row.userName + "]?", t("msg.remind"), {
    confirmButtonText: t("button.confirm"),
    cancelButtonText: t("button.cancel"),
    type: "warning"
  })
    .then(async () => {
      try {
        await updateStatus(row.userId, row.userStatus);
        koiMsgSuccess(t("msg.success"));
      } catch (error) {
        console.log(error);
        row.userStatus = row.userStatus == "0" ? "1" : "0";
        handleTableData();
        koiMsgError(t("msg.fail"));
      }
    })
    .catch(() => {
      row.userStatus = row.userStatus == "0" ? "1" : "0";
      koiMsgWarning(t("msg.cancelled"));
    });
};

// 分配角色对话框
const koiRoleDialogRef = ref();
// 左侧所有数据
const transferLeftRoleList = ref<any>([]);
// 右侧选择数据
const transferRightRoleList = ref<any>([]);

const handleAssignRoles = async () => {
  if (ids.value.length == 0) {
    koiMsgWarning(t("msg.selectData"));
    return;
  }

  transferLeftRoleList.value = [];
  transferRightRoleList.value = [];

  koiRoleDialogRef.value.koiOpen();

  try {
    // 传递当前登录用户ID
    const res: any = await listNormalTransferRole(ids.value);
    transferLeftRoleList.value = res.data.data1; // 左侧所有数据，右边出现一样的会自动进行去除
    if (ids.value.length > 1) {
      transferRightRoleList.value = [];
    } else {
      transferRightRoleList.value = res.data.data2;
    }
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }
};

/** 角色列表元素变化时触发，value 是 最终右侧选中的数据 */
const handleRoleTransferChange = async (value: any) => {
  if (ids.value.length == 0) {
    koiMsgWarning(t("msg.selectData"));
    return;
  }

  try {
    await assignRolesToUsers({ userIds: ids.value, roleIds: value });
    koiMsgSuccess(t("msg.success"));
  } catch (error) {
    console.log(error);
    handleAssignRoles();
    koiMsgError(t("msg.fail"));
  }
};

// 分配岗位对话框
const koiPostDialogRef = ref();
// 左侧所有数据
const transferLeftPostList = ref<any>([]);
// 右侧选择数据
const transferRightPostList = ref<any>([]);

const handleAssignPosts = async () => {
  if (ids.value.length == 0) {
    koiMsgWarning(t("msg.selectData"));
    return;
  }

  transferLeftPostList.value = [];
  transferRightPostList.value = [];

  try {
    // 传递当前登录用户ID
    const res: any = await listNormalTransferPost(ids.value);
    transferLeftPostList.value = res.data.data1; // 左侧所有数据，右边出现一样的会自动进行去除
    transferRightPostList.value = res.data.data2;
    if (ids.value.length > 1) {
      transferRightPostList.value = [];
    } else {
      transferRightPostList.value = res.data.data2;
    }
  } catch (error) {
    console.log(error);
    koiMsgError(t("msg.fail"));
  }

  koiPostDialogRef.value.koiOpen();
};

/** 岗位列表元素变化时触发，value 是 最终右侧选中的数据 */
const handlePostTransferChange = async (value: any) => {
  if (ids.value.length == 0) {
    koiMsgWarning(t("msg.selectData"));
    return;
  }

  try {
    await assignPostsToUsers({ userIds: ids.value, postIds: value });
    koiMsgSuccess(t("msg.success"));
  } catch (error) {
    console.log(error);
    handleAssignPosts();
    koiMsgError(t("msg.fail"));
  }
};

/** 删除 */
const handleDelete = (row: any) => {
  const id = row.userId;
  if (id == null || id == "") {
    koiMsgWarning(t("msg.selectData"));
    return;
  }
  ElMessageBox.confirm(t("msg.confirmDelete"), t("msg.remind"), {
    confirmButtonText: t("button.confirm"),
    cancelButtonText: t("button.cancel"),
    type: "warning"
  })
    .then(async () => {
      try {
        await deleteById(id);
        handleTableData();
        koiMsgSuccess(t("msg.success"));
      } catch (error) {
        console.log(error);
        handleTableData();
        koiMsgError(t("msg.fail"));
      }
    })
    .catch(() => {
      koiMsgWarning(t("msg.cancelled"));
    });
};

/** 批量删除 */
const handleBatchDelete = () => {
  if (ids.value.length == 0) {
    koiMsgWarning(t("msg.selectData"));
    return;
  }
  ElMessageBox.confirm(t("msg.confirmDelete"), t("msg.remind"), {
    confirmButtonText: t("button.confirm"),
    cancelButtonText: t("button.cancel"),
    type: "warning"
  })
    .then(async () => {
      try {
        await batchDelete(ids.value);
        handleTableData();
        koiMsgSuccess(t("msg.success"));
      } catch (error) {
        console.log(error);
        handleTableData();
        koiMsgError(t("msg.fail"));
      }
    })
    .catch(() => {
      koiMsgWarning(t("msg.cancelled"));
    });
};

/** 重置密码 */
const handleResetPwd = (row: any) => {
  const id = row.userId;
  if (id == null || id == "") {
    koiMsgWarning(t("msg.selectData"));
    return;
  }

  const inputPattern = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9]{6,20}$/;

  ElMessageBox.prompt(t("menu.system.user.rules.password.required"), t("msg.remind"), {
    confirmButtonText: t("button.confirm"),
    cancelButtonText: t("button.cancel"),
    type: "warning",
    inputPattern: inputPattern,
    inputErrorMessage: t("menu.system.user.rules.password.validator"),
    draggable: true
  })
    .then(async (res: any) => {
      const loading = ElLoading.service({
        lock: true,
        text: "Loading"
      });
      await resetPwd(id, res.value);
      loading.close();
      koiMsgSuccess(t("msg.success"));
    })
    .catch(() => {
      koiMsgWarning(t("msg.cancelled"));
    });
};

// 导出loading
const excelLoading = ref(false);

/** 数据导出 */
const handleExportExcel = async (params: any) => {
  console.log("params:", params);
  try {
    excelLoading.value = true;
    const res: any = await exportData(params);
    const objectUrl = URL.createObjectURL(
      new Blob([res.data], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      })
    );
    const link = document.createElement("a");
    // 设置导出的文件名称
    link.download = "用户数据" + Date.now() + ".xlsx";
    link.style.display = "none";
    link.href = objectUrl;
    link.click();
    document.body.appendChild(link);
    excelLoading.value = false;
  } catch (error) {
    console.error(error);
    koiMsgWarning(t("msg.cancelled"));
    excelLoading.value = false;
  }
};

/** Excel组件 */
const koiExcelRef = ref();

/** 下载模板 */
const handleTemplateExcel = async () => {
  try {
    const res: any = await downloadTemplate();
    const objectUrl = URL.createObjectURL(
      new Blob([res.data], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      })
    );
    const link = document.createElement("a");
    // 设置导出的文件名称
    link.download = "用户下载模板" + Date.now() + ".xlsx";
    link.style.display = "none";
    link.href = objectUrl;
    link.click();
    document.body.appendChild(link);
  } catch (error) {
    console.error(error);
    koiMsgWarning(t("msg.cancelled"));
  }
};

/** 数据导入 */
const handleImportExcel = () => {
  let params = {
    title: "导入数据",
    importApi: import.meta.env.VITE_SERVER + "/koi/sysLoginUser/importExcelData"
  };
  koiExcelRef.value.excelParams(params);
};
</script>

<style lang="scss" scoped>
// 穿梭框高度调整
:deep(.el-transfer-panel__body) {
  height: 400px;
}
</style>
